Frontend Forever App
We have a mobile app for you to download and use. And you can unlock many features in the app.
Get it now
Intall Later
Run
HTML
CSS
Javascript
Output
Document
@charset "UTF-8"; @import url(https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800); *, :after, :before { box-sizing: border-box; padding: 0; margin: 0; } @use "sass:map"; $dur: 4s; $ease-in: cubic-bezier(0.32,0,0.67,0); $ease-out: cubic-bezier(0.33,1,0.68,1); $ease-in-out: cubic-bezier(0.65,0,0.35,1); // mixins @mixin borders1-start() { border: { top-color: hsla(0,0%,0%,0.1); right-color: hsla(0,0%,0%,0.1); bottom-color: hsla(0,0%,100%,0.1); left-color: hsla(0,0%,100%,0.3); }; } @mixin borders2-start() { border: { top-color: hsla(0,0%,0%,0.1); right-color: hsla(0,0%,100%,0.1); bottom-color: hsla(0,0%,100%,0.3); left-color: hsla(0,0%,0%,0.1); }; } @mixin borders3-start() { border: { top-color: hsla(0,0%,100%,0.1); right-color: hsla(0,0%,100%,0.3); bottom-color: hsla(0,0%,0%,0.1); left-color: hsla(0,0%,0%,0.1); }; } @mixin borders-end() { border: { top-color: hsla(0,0%,100%,0.3); right-color: hsla(0,0%,0%,0.1); bottom-color: hsla(0,0%,0%,0.1); left-color: hsla(0,0%,100%,0.1); }; } // block configurations $blocks: ( ( "color": var(--blue), "x": 7, "y": 7, "w": 2, "h": 3, "areas": "x a" "x b" "c d", "transform1": translate(5em,0) rotate(90deg), "transform2": translate(7em,0) rotate(90deg), "transform3": translate(7em,0) rotate(0), "transform4": translate(7em,7em) rotate(0), "effect": true, "effect-type": 1 ), ( "color": var(--cyan), "x": 0, "y": 9, "w": 4, "h": 1, "areas": "a b c d", "transform1": translate(3em,0), "transform2": translate(0,0), "transform3": translate(0,1em), "transform4": translate(0,9em) ), ( "color": var(--green), "x": 5, "y": 8, "w": 3, "h": 2, "areas": "x a b" "c d y", "transform1": translate(4em,0), "transform2": translate(5em,0), "transform3": translate(5em,1em), "transform4": translate(5em,8em) ), ( "color": var(--yellow), "x": 1, "y": 7, "w": 2, "h": 2, "areas": "a b" "c d", "transform1": translate(5em,0), "transform2": translate(0,0), "transform3": translate(1em,0), "transform4": translate(1em,7em) ), ( "color": var(--purple), "x": 4, "y": 7, "w": 2, "h": 3, "areas": "a x" "b c" "d y", "transform1": translate(5em,0) rotate(90deg), "transform2": translate(4em,0) rotate(90deg), "transform3": translate(4em,0) rotate(0), "transform4": translate(4em,7em) rotate(0), "effect": true, "effect-type": 1 ), ( "color": var(--red), "x": 4, "y": 6, "w": 3, "h": 2, "areas": "a b x" "y c d", "transform1": translate(4em,0), "transform2": translate(5em,0), "transform3": translate(4em,0), "transform4": translate(4em,6em) ), ( "color": var(--orange), "x": 2, "y": 6, "w": 2, "h": 3, "areas": "a b" "x c" "x d", "transform1": translate(6em,0) rotate(90deg), "transform2": translate(2em,0) rotate(90deg), "transform3": translate(2em,0) rotate(0), "transform4": translate(2em,6em) rotate(0), "effect": true, "effect-type": 1 ), ( "color": var(--purple), "x": 6, "y": 6, "w": 3, "h": 2, "areas": "a b c" "x d y", "transform1": translate(5em,0) rotate(180deg), "transform2": translate(6em,0) rotate(180deg), "transform3": translate(6em,0) rotate(0), "transform4": translate(6em,6em) rotate(0), "effect": true, "effect-type": 2 ), ( "color": var(--blue), "x": 0, "y": 6, "w": 2, "h": 3, "areas": "a b" "c x" "d x", "transform1": translate(4em,0) rotate(-90deg), "transform2": translate(3em,0) rotate(0), "transform3": translate(0,0) rotate(0), "transform4": translate(0,6em) rotate(0), "effect": true, "effect-type": 3 ), ( "color": var(--cyan), "x": 9, "y": 6, "w": 1, "h": 4, "areas": "a" "b" "c" "d", "transform1": translate(5em,0) rotate(90deg), "transform2": translate(9em,0) rotate(0), "transform3": translate(9em,0) rotate(0), "transform4": translate(9em,6em) rotate(0), "effect": true, "effect-type": 4 ) ); // styles *, *:before, *:after { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { --hue: 223; --bg: hsl(var(--hue),10%,90%); --fg: hsl(var(--hue),10%,10%); --red: hsl(3,90%,50%); --orange: hsl(33,90%,50%); --yellow: hsl(48,90%,50%); --green: hsl(123,90%,40%); --cyan: hsl(183,90%,40%); --blue: hsl(243,90%,50%); --purple: hsl(273,90%,50%); --trans-dur: 0.3s; font-size: calc(14px + (60 - 14) * (100vw - 280px) / (3840 - 280)); } body { background-color: var(--bg); color: var(--fg); display: flex; font: 1em/1.5 sans-serif; height: 100vh; transition: background-color var(--trans-dur), color var(--trans-dur); } main { margin: auto; padding: 1.5em 0; } .tetris { animation-name: bounce; position: relative; width: 10em; height: 10.5em; &:after { background-color: hsl(var(--hue),10%,70%); content: ""; display: block; position: absolute; bottom: 0; left: 0; width: 100%; height: 0.5em; transition: background-color var(--trans-dur); } &, &__block, &__block-cell { animation: { duration: $dur; timing-function: $ease-in-out; iteration-count: infinite; }; } &__block { display: grid; position: absolute; top: 0; left: 0; transform-origin: 1em 1em; $letters: a b c d; &-cell { border: 0.25em solid hsla(0,0%,0%,0) { top-color: hsla(0,0%,100%,0.3); right-color: hsla(0,0%,0%,0.1); bottom-color: hsla(0,0%,0%,0.1); left-color: hsla(0,0%,100%,0.1); }; @for $l from 1 through length($letters) { &:nth-child(#{$l}) { grid-area: nth($letters,$l); } } } @for $b from 1 through length($blocks) { $block: nth($blocks,$b); &--#{$b} { animation-name: block#{$b}; grid-template: { areas: map.get($block,"areas"); columns: repeat(map.get($block,"w"),1fr); rows: repeat(map.get($block,"h"),1fr); }; width: map.get($block,"w") * 1em; height: map.get($block,"h") * 1em; transform: translate(map.get($block,"x") * 1em,map.get($block,"y") * 1em); } &--#{$b} &-cell { @if map.get($block,"effect") == true { animation-name: block#{$b}-borders; } background-color: map.get($block,"color"); } } } } /* Dark theme */ @media (prefers-color-scheme: dark) { :root { --bg: hsl(var(--hue),10%,10%); --fg: hsl(var(--hue),10%,90%); } .tetris { &:after { background-color: hsl(var(--hue),10%,30%); } } } /* Animations */ @keyframes bounce { from, 96%, to { animation-timing-function: linear; transform: translate(0,0); } 98% { animation-timing-function: $ease-out; transform: translate(0,1em); } } @for $b from 1 through length($blocks) { $block: nth($blocks,$b); $inc: 9.6%; // block movements @keyframes block#{$b} { from { @if $b > 1 { animation-timing-function: steps(1,end); visibility: hidden; } transform: map.get($block,"transform1"); } @if $b > 1 { #{$inc * ($b - 1)} { animation-timing-function: $ease-in-out; visibility: visible; transform: map.get($block,"transform1"); } } #{$inc * ($b - 1) + ($inc / 3)} { transform: map.get($block,"transform2"); } #{$inc * ($b - 1) + ($inc / 3) * 2} { animation-timing-function: $ease-in; transform: map.get($block,"transform3"); } #{$inc * ($b - 1) + $inc}, 98% { animation-timing-function: $ease-out; opacity: 1; transform: map.get($block,"transform4"); } to { opacity: 0; transform: map.get($block,"transform4"); } } // lighting effects @if map.get($block,"effect") == true { @keyframes block#{$b}-borders { $effectType: map.get($block,"effect-type"); @if $effectType == 1 { from, #{$inc * ($b - 1) + ($inc / 3)} { @include borders1-start(); } #{$inc * ($b - 1) + ($inc / 3) * 2}, to { @include borders-end(); } } @else if $effectType == 2 { from, #{$inc * ($b - 1) + ($inc / 3)} { @include borders2-start(); } #{$inc * ($b - 1) + ($inc / 3) * 2}, to { @include borders-end(); } } @else if $effectType == 3 { @if $b == 1 { from { @include borders3-start(); } } @else { from, #{$inc * ($b - 1)} { @include borders3-start(); } } #{$inc * ($b - 1) + ($inc / 3)}, to { @include borders-end(); } } @else if $effectType == 4 { @if $b == 1 { from { @include borders1-start(); } } @else { from, #{$inc * ($b - 1)} { @include borders1-start(); } } #{$inc * ($b - 1) + ($inc / 3)}, to { @include borders-end(); } } } } }
console.log("Event Fired")